#include "Utility.h"

namespace hitcrt {

std::string formatTime(const time_t time) {
    struct tm tm;
    localtime_r(&time, &tm);
    char formattedTime[20];
    char *timePtr = formattedTime;
    sprintf(timePtr, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
            tm.tm_hour, tm.tm_min, tm.tm_sec);
    std::string result = timePtr;
    return result;
}

// 转换为C风格的时间类型time_t

std::string formatTime(const std::chrono::system_clock::time_point tp) {
    time_t tt = std::chrono::system_clock::to_time_t(tp);
    return formatTime(tt);
}

cv::Mat createRandomImage(const int width, const int height) {
    cv::Mat img = cv::Mat::zeros(cv::Size(width, height), CV_8UC3);
    cv::randu(img, cv::Scalar::all(0), cv::Scalar::all(255));
    return img;
}

inline bool isFileExist(const std::string &name) {
    // POSIX函数方法
    struct stat buffer;
    return (stat(name.c_str(), &buffer) == 0);

    // fopen方法
    // if (FILE *file = fopen(name.c_str(), "r"))
    // {
    //     fclose(file);
    //     return true;
    // }
    // else
    // {
    //     return false;
    // }
}

FPS::FPS(const std::string &name) : m_name(name) {
    m_realFPS = 0;
    m_avgFPS = 0;
    m_fiveSecFPS = 0;
    m_fiveSecCnt = 0;
    m_total = 0;

    m_isTic = false;
    m_is5SecStart = false;
}

FPS::FPS() {
    m_realFPS = 0;
    m_avgFPS = 0;
    m_fiveSecFPS = 0;
    m_fiveSecCnt = 0;
    m_total = 0;
    m_name = "Unknown";

    m_isTic = false;
    m_is5SecStart = false;
}

void FPS::calc() {
    toc();
    tic();
}

void FPS::tic() {
    if (!m_is5SecStart) {
        m_fiveSecTic = std::chrono::system_clock::now();
        m_is5SecStart = true;
    }
    m_tic = std::chrono::system_clock::now();
    m_isTic = true;
}

void FPS::toc() {
    if (!m_isTic) {
        return;
    } else {
        m_isTic = false;
    }
    auto toc = std::chrono::system_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(toc - m_tic);
    double realCost = double(duration.count()) * std::chrono::microseconds::period::num /
                      std::chrono::microseconds::period::den;
    double realFPS = 1 / realCost;
    // 实时
    m_realCost = realCost;
    m_realFPS = realFPS;
    // 总平均
    m_total++;  // uint溢出自动重置0,不会出现负值
    double lastAvgFPS = m_avgFPS, lastAvgCost = m_avgCost;
    if (m_total > 0) {
        m_avgFPS = (m_total - 1.0) / m_total * lastAvgFPS + realFPS / m_total;
        m_avgCost = (m_total - 1.0) / m_total * lastAvgCost + realCost / m_total;
    } else {
        m_avgFPS = realFPS;
        m_avgCost = realCost;
    }
    // 最近5s的平均
    duration = std::chrono::duration_cast<std::chrono::microseconds>(toc - m_fiveSecTic);
    double pastSecs = double(duration.count()) * std::chrono::microseconds::period::num /
                      std::chrono::microseconds::period::den;
    m_fiveSecCnt++;
    m_fiveSecCost = m_fiveSecCost + realCost;
    if (pastSecs > 5.0) {
        m_fiveSecFPS = m_fiveSecCnt / m_fiveSecCost;
        m_fiveSecCnt = 0;
        m_fiveSecCost = 0.0;
        m_fiveSecTic = toc;
    }
}

void FPS::showFPS() const {
    std::cout << m_name << " fps< real: " << m_realFPS << " avg: " << m_avgFPS << " 5sec: " << m_fiveSecFPS
              << " >" << std::endl;
}

void FPS::showCost() const {
    std::cout << m_name << " cost< real: " << m_realCost << " avg: " << m_avgCost
              << " 5sec: " << m_fiveSecCost << " >" << std::endl;
}

void FPS::setName(const std::string &name) { m_name = name; }

std::string FPS::getName() const { return m_name; }
double FPS::getRealFPS() const { return m_realFPS; }
double FPS::getAvgFPS() const { return m_avgFPS; }
double FPS::get5SecFPS() const { return m_fiveSecFPS; }
double FPS::getRealCost() const { return m_realCost; }
double FPS::getAvgCost() const { return m_avgCost; }
double FPS::get5SecCost() const { return m_fiveSecCost; }

}  // namespace hitcrt
